﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Affinity.Core.Collections
{
    public class SynchronizedList<TItem> : IList<TItem>
    {
        public SynchronizedList()
        {
        }
        
        public void Add(TItem value)
        {
            lock (_Sync) _InnerList.Add(value);
        }

        public void AddIfNotPresent(TItem value)
        {
            lock (_Sync) if (!_InnerList.Contains(value)) _InnerList.Add(value);
        }

        public void Clear()
        {
            lock (_Sync) _InnerList.Clear();
        }

        public bool Contains(TItem value)
        {
            lock (_Sync) return _InnerList.Contains(value);
        }

        public int IndexOf(TItem value)
        {
            lock (_Sync) return _InnerList.IndexOf(value);
        }

        public void Insert(int index, TItem value)
        {
            lock (_Sync) _InnerList.Insert(index, value);
        }
        
        public bool IsReadOnly
        {
            get { lock (_Sync) return _InnerList.IsReadOnly; }
        }

        public bool Remove(TItem value)
        {
            lock (_Sync) return _InnerList.Remove(value);
        }

        public void RemoveAt(int index)
        {
            lock (_Sync) _InnerList.RemoveAt(index);
        }

        public TItem this[int index]
        {
            get { lock (_Sync) return _InnerList[index]; }
            set { lock (_Sync) _InnerList[index] = value; }
        }

        public void CopyTo(TItem[] array, int index)
        {
            lock (_Sync) _InnerList.CopyTo(array, index);
        }

        public int Count
        {
            get { lock (_Sync) return _InnerList.Count; }
        }
        
        public object SyncRoot
        {
            get { return _Sync; }
        }

        public IEnumerator<TItem> GetEnumerator()
        {
            lock (_Sync) return ((IEnumerable<TItem>)_InnerList.ToArray()).GetEnumerator();
        }

        public TItem[] ToArrayAndClear()
        {
            lock (_Sync)
            {
                TItem[] array = _InnerList.ToArray();
                _InnerList.Clear();
                return array;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
        
        private readonly IList<TItem> _InnerList = new List<TItem>();
        private readonly object _Sync = new object();
    }
}
